#include "LineEditShell.h"
#include <QDebug>

XX_KEY_C(LineEditShell, kInputExpression, "inputExpression");
XX_KEY_C(LineEditShell, kMatchExpression, "matchExpression");

XX_KEY_C(LineEditShell,kIsMatching,"isMatching");

XX_KEY_C(LineEditShell, kSigTextChanged, "sigTextChanged");
XX_KEY_C(LineEditShell, kPreviousText, "previousText");
XX_KEY_C(LineEditShell, kCurrentText, "currentText");


LineEditShell::LineEditShell(QObject *parent)
    :ShellBase(parent){
    _inputExpression = nullptr;
    _matchExpression = nullptr;
	_isMatching = false;
}

void LineEditShell::shell(QLineEdit *lineEdit){
    ShellBase::shell(lineEdit);
}

void LineEditShell::config(const QVariant &param) {
    if (param.type() == QVariant::Map) {
        auto map = param.toMap();
        if(map.contains(kInputExpression)){
            configInputExpression(map[kInputExpression].toString());
        }
        if(map.contains(kMatchExpression)){
            configMatchExpression(map[kMatchExpression].toString());
        }
	}
	else {

	}
}
void LineEditShell::configExpression(const QString &input, const QString &match){
    configInputExpression(input);
    configMatchExpression(match);
}
void LineEditShell::configInputExpression(const QString &expression){
    _inputExpression.reset(expression.isEmpty()?nullptr:new QRegExp(expression));
}
void LineEditShell::configMatchExpression(const QString &expression){
    _matchExpression.reset(expression.isEmpty()?nullptr:new QRegExp(expression));
}

QVariant LineEditShell::action(const QString &name, const QVariant &info){
    Q_UNUSED(info)
    if(name == kIsMatching){
        return isMatching();
    }
    return  QVariant();
}

void LineEditShell::installTarget(const QString &name, QObject *target){
    if(!name.isEmpty()){
        return;
    }
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(target);
    Q_ASSERT(nullptr != lineEdit);
    connect(lineEdit, &QLineEdit::textEdited, this, &LineEditShell::onTextEdited);
    connect(lineEdit, &QLineEdit::textChanged, this, &LineEditShell::onTextChanged);

    _isMatching = match(lineEdit->text());
}
void LineEditShell::uninstallTarget(const QString &name, QObject *target){
    if(!name.isEmpty()){
        return;
    }
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(target);
    Q_ASSERT(nullptr != lineEdit);
    disconnect(lineEdit, &QLineEdit::textEdited, this, &LineEditShell::onTextEdited);
    disconnect(lineEdit, &QLineEdit::textChanged, this, &LineEditShell::onTextChanged);
}

void LineEditShell::onTextEdited(QString text) {
    QLineEdit *target = qobject_cast<QLineEdit*>(sender());

    if (input(text)) {
        target->setText(_currentText);
        return;
    }
    _isMatching = match(text);

    QString previousText = _currentText;
    _currentText = target->text();
    QVariantMap info = {{kPreviousText,previousText},{kCurrentText,_currentText},{kIsMatching,_isMatching}};
    emit sigEvent(kSigTextChanged,info);
    textDidChanged(previousText,_currentText);
}
void LineEditShell::onTextChanged(QString text) {

}

bool LineEditShell::input(const QString &text){
    return nullptr==_inputExpression || !_inputExpression->exactMatch(text);
}
bool LineEditShell::match(const QString &text){
    return nullptr==_matchExpression || _matchExpression->exactMatch(text);
}
